package ch.ethz.fcl.metrobuzz.render.custom;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;

import org.lwjgl.opengl.GL11;

import ch.ethz.fcl.metrobuzz.data.scene.spacetime.Trip;
import ch.ethz.fcl.metrobuzz.render.AbstractRenderer;
import ch.ethz.fcl.metrobuzz.render.techniques.vbo.ArrayBufferObject;
import ch.ethz.fcl.metrobuzz.tools.MBTools;

public class AgentRenderer extends AbstractRenderer {
	private boolean initialized = false;
	public static boolean render_bounds = false;
	public static boolean render_stops = false;
	public static boolean render_map = false;
	public static int level = 0;

	private ArrayBufferObject stopBuffer;

	private ArrayBufferObject[] trip_cluster_buffer;
	ArrayList<ArrayList<Integer>> sub_nodes_index;

	// for network
	NetworkRenderer netRend = null;

	// these agents are used for displaying the selected agents
	int nrAgents = 10000;

	// these are used for displaying the non selected agents
	int nrOutgreyedAgents = 5000;

	// display list for outgrayed agents
	private int agentDisplayList = -1;

	// called by Renderer
	@Override
	public void update() {
		if (!initialized) {
			init();
			initialized = true;
		}
	}

	// called by renderer
	@Override
	public void render() {
		// setup up scene
		// setupScene();

		// if (render_stops) {
		// GL11.glPushMatrix();
		// GL11.glTranslatef(-.7f, 0.2f, 0f);
		// renderStops();
		// GL11.glPopMatrix();
		// }

		if (render_map) {
			GL11.glPushMatrix();
			GL11.glTranslatef(-.7f, 0.2f, 0f);
			enableBlend();
			lineSmooth();
			// renderBoundaries();
			GL11.glPopMatrix();
		}
	}

	public void init() {
//		if (scene == null) {
//			initialized = false;
//			return;
//		}
//
//		if (controller == null) {
//			initialized = false;
//			return;
//		}
//
//		agents = scene.getAgents();
//
//		// initTripClusterBuffer();
//
//		nrAgents = Math.min(nrAgents, agents.size());
//		nrOutgreyedAgents = Math.min(nrOutgreyedAgents, nrAgents);
//
//		// createAgentDisplayList();
//
//		// netRend = new DefaultNetworkRenderer(scene, nodes, links);
//
//		// MBTools.print(
//		// Arrays.copyOfRange(scene.getEdgeWeight(), 0, 100));
//		MBTools.debug("Scene edge size " + scene.getEdges().size(), false);
	}

	void initTripClusterBuffer() {
		// sub_nodes_index = scene.getSpatialIndex().getSubNodesLevel((2));
		int size = sub_nodes_index.size();
		trip_cluster_buffer = new ArrayBufferObject[size];

		for (int i = 0; i < size; i++) {
			trip_cluster_buffer[i] = new ArrayBufferObject();
			initTripClusterBuffer(sub_nodes_index.get(i),
					trip_cluster_buffer[i]);
		}

	}

	@SuppressWarnings("null")
	private void initTripClusterBuffer(ArrayList<Integer> trip_index,
			ArrayBufferObject tripBuffer) {
		ArrayList<Trip> trips = new ArrayList<Trip>();
		int trip_line_segment_size = 0;
		for (int i = 0; i < trip_index.size(); i++) {
			Trip trip = null;
			trips.add(trip);

			for (Trip.TripSegment ts : trip.getTripSegments())
				trip_line_segment_size += ts.getNodesIndices().length - 1;
		}

		ByteBuffer bb = ByteBuffer
				.allocateDirect(trip_line_segment_size * 2 * 3 * 8);
		bb.order(ByteOrder.nativeOrder());
		FloatBuffer buffer = bb.asFloatBuffer();

		for (int i = 0; i < trips.size(); i++) {
			// for (Trip.TripSegment ts : trips.get(i).getTripSegments())
			// ts.put(buffer);
		}
		tripBuffer.load(buffer);
	}

	void renderTripClusters() {
		int render_size = Math.min(trip_cluster_buffer.length, 10);
		for (int i = 0; i < render_size; i++) {
			float color_r = ((float) i + 1) / render_size;
			GL11.glPushMatrix();
			MBTools.debug(color_r + "'" + " " + i, false);
			GL11.glColor4f(color_r, 1 - color_r, 0, color_r);
			trip_cluster_buffer[i].draw(GL11.GL_LINES);
			GL11.glPopMatrix();
		}
	}

	void renderStops() {
		GL11.glPushMatrix();
		GL11.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
		GL11.glPointSize(2.0f);

		GL11.glEnable(GL11.GL_BLEND);
		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

		GL11.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_NICEST);
		GL11.glEnable(GL11.GL_LINE_SMOOTH);

		GL11.glHint(GL11.GL_POINT_SMOOTH_HINT, GL11.GL_NICEST);
		GL11.glEnable(GL11.GL_POINT_SMOOTH);

		stopBuffer.draw(GL11.GL_POINTS);

		GL11.glDisable(GL11.GL_BLEND);

		GL11.glPopMatrix();
	}

	void createAgentDisplayList() {
		agentDisplayList = GL11.glGenLists(1);
		GL11.glNewList(agentDisplayList, GL11.GL_COMPILE);

		GL11.glEndList();
	}

	@SuppressWarnings("unused")
	private void renderAgentDisplayList() {
		if (agentDisplayList < 0) {
			MBTools.debug(
					"AgentRenderer.renderAgentDisplayList agentDisplayList = "
							+ agentDisplayList, true);
			return;
		}
		GL11.glCallList(this.agentDisplayList);
	}

}
